package com.appspot.seqpop.service;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;

import com.appspot.seqpop.model.Sequence;

public class FastaReader implements Closeable {

    private static final char HEADER_LINE_MARK = '>';

    private final BufferedReader reader;
    private String nextLine;

    public FastaReader(String fasta) throws IOException {
        reader = new BufferedReader(new StringReader(fasta));
        initialize();
    }

    public FastaReader(InputStream fastaStream) throws IOException {
        reader = new BufferedReader(new InputStreamReader(fastaStream));
        initialize();
    }

    private void initialize() throws IOException {
        do {
            nextLine = reader.readLine();
        } while (!isEndOfStream() && !isEntryStart());
    }

    public boolean hasNext() {
        return isEntryStart();
    }

    public Sequence getNextSequence() throws IOException, IllegalStateException {
        if (isEndOfStream()) {
            return null;
        }
        if (!isEntryStart()) {
            throw new IllegalStateException();
        }

        String description = nextLine.substring(1);
        StringBuilder sequence = new StringBuilder();
        while (true) {
            nextLine = reader.readLine();
            if (isEndOfStream() || isEntryStart()) {
                break;
            }
            sequence.append(nextLine);
        }
        return new Sequence(description, sequence.toString());
    }

    private boolean isEndOfStream() {
        return nextLine == null;
    }

    private boolean isEntryStart() {
        return nextLine != null && (!nextLine.isEmpty() && nextLine.charAt(0) == HEADER_LINE_MARK);
    }

    public void close() throws IOException {
        reader.close();
    }
}
